using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using Framework.Core;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.SceneManagement;

namespace Framework
{
    public class BundleAssetLoader : AssetLoader
    {
        private string _assetPath;
        private AssetsInfo _assetsInfo;
        private readonly Dictionary<string, string> _assetNameToBundleNameMap;
        private AssetBundleManifest _manifest;
        private readonly List<string> _driectDependencies = new(128);

        private readonly Dictionary<string, string[]> _dependenciesMap = new(128);
        private readonly Dictionary<string, BundleData> _tempDependenciesMap = new(128);
        private readonly List<BundleData> _tempDependenciesList = new(128);

        private bool _checkWorkingLoadDataList;
        private readonly List<AssetLoadData> _workingLoadDataList;

        private CustomPool<BundleData> _bundleDataPool;
        private readonly Dictionary<string, BundleData> _bundleDataMap;

        private CustomPool<AssetData> _assetDataPool;
        private readonly Dictionary<string, AssetData> _assetDataMap;

        private bool _checkWorkingAssetDataList;
        private readonly List<string> _workingAssetDataList;

        private readonly CustomPool<LoadBundleItem> _loadBundleItemPool;

        private readonly Queue<LoadBundleItem> _loadBundleQueue;

        private bool _checkUnloadBundles;
        private readonly Queue<BundleData> _unloadBundles;
        //资源来源
        private readonly Dictionary<string, BundleFileInfo> _bundleFileInfo;
        private BundleDownload _downloader;
        private readonly LoaderContext _loaderContext;
        public BundleAssetLoader()
        {
            _assetNameToBundleNameMap = new Dictionary<string, string>();
            _workingLoadDataList = new List<AssetLoadData>();
            _bundleDataMap = new Dictionary<string, BundleData>();
            _assetDataMap = new Dictionary<string, AssetData>();
            _workingAssetDataList = new List<string>();
            _loadBundleItemPool = new CustomPool<LoadBundleItem>(() => { return new LoadBundleItem(); });
            _loadBundleQueue = new Queue<LoadBundleItem>();
            _unloadBundles = new Queue<BundleData>();
            _bundleFileInfo = new Dictionary<string, BundleFileInfo>();
            _loaderContext = new LoaderContext
            {
                StreamingAssetsPath = Application.streamingAssetsPath,
                MaxSizeOfEncryptFile = 0
            };
            _bundleFileInfo.Clear();
        }
        protected override void onUpdate(float deltaTime, float unscaledDeltaTime)
        {
            base.onUpdate(deltaTime, unscaledDeltaTime);
            if (!Enabled) return;
            int len;
            if (_checkWorkingAssetDataList)
            {
                _checkWorkingAssetDataList = false;
                len = _workingAssetDataList.Count;
                while (len-- > 0)
                {
                    var path = _workingAssetDataList[len];
                    if (_assetDataMap.TryGetValue(path, out AssetData assetData))
                    {
                        assetData.Execute();
                        if (assetData.Bundles.Count < 1)
                        {
                            _workingAssetDataList.RemoveAt(len);
                            _loaderContext.CoroutineManager.Start(assetData.Load(loadAssetFinish), assetData.LoadData.Path);
                        }
                    }
                    else
                    {
                        _workingAssetDataList.RemoveAt(len);
                    }
                    if (IdleTime < 0f)
                    {
                        //break;
                    }
                }
            }

            if (_checkWorkingLoadDataList)
            {
                _checkWorkingLoadDataList = false;
                len = _workingLoadDataList.Count;
                while (len-- > 0)
                {
                    var loadData = _workingLoadDataList[len];
                    if (_assetDataMap.TryGetValue(loadData.Path, out AssetData assetData))
                    {
                        if (assetData.Finished)
                        {
                            _workingLoadDataList.RemoveAt(len);
                            if (loadData.IsScene)
                            {
                                loadData.Finish(assetData.SceneAsset);
                            }
                            else
                            {
                                loadData.Finish(assetData.Asset);
                            }
                        }
                    }
                }
            }

            len = _loadBundleQueue.Count;
            while (len-- > 0)
            {
                var item = _loadBundleQueue.Dequeue();
                if (item.BundleData.RefCount > 0)
                {
                    if (item.Info.From == FileLoadFrom.Download)
                    {
                        _downloader.Download(item.Info.Info);
                    }
                    else
                    {
                        _loaderContext.AssetProcessor = _assetProcessor;
                        _loaderContext.CoroutineManager.Start(item.Load(_loaderContext, _assetPath, loadBundleFinish), item.Info.Info.Path);
                    }
                }
                if (IdleTime < 0f)
                {
                    //break;
                }
            }
            if (_checkUnloadBundles)
            {
                _checkUnloadBundles = false;
                foreach (var item in _bundleDataMap)
                {
                    if (item.Value.RefCount < 1)
                    {
                        if (_assetProcessor != null)
                        {
                            if (_assetProcessor.DontUnloadBundle(item.Value.Path))
                            {
                                continue;
                            }
                        }
                        _unloadBundles.Enqueue(item.Value);
                    }
                }

                len = _unloadBundles.Count;
                if (len > 0)
                {
                    this.unloadCount = len;
                    while (len-- > 0)
                    {
                        var item = _unloadBundles.Dequeue();
                        item.Release();
                        if (item.AssetBundle == null)
                        {
                            _bundleDataMap.Remove(item.Path);
                            _bundleDataPool.Release(item);
                            if (_assetProcessor != null)
                            {
                                _assetProcessor.OnUnloadBundle(item.Path);
                            }
                        }
                    }
                    Resources.UnloadUnusedAssets();
                }
                //long beforeMem = GC.GetTotalMemory(false) / 1024;
                //long afterMem = GC.GetTotalMemory(true) / 1024;
                //FrameworkLog.LogWarningFormat("memBefore :{0} memAfter :{1} inc:{2}", beforeMem, afterMem, afterMem - beforeMem);

            }
            // FrameworkLog.LogErrorFormat("working assetdata count {0}", _workingAssetDataList.Count);
            // FrameworkLog.LogErrorFormat("working bundledata count {0}", _workinBundleDataList.Count);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="versionFilePath">Android/version.json</param>
        /// <param name="coroutineManager"></param>
        /// <param name="downloader"></param>
        public void Initialize(string versionFilePath, ICoroutineManager coroutineManager, BundleDownload downloader)
        {
            if (_assetPath != null) return;
            _loaderContext.CoroutineManager = coroutineManager;
            _downloader = downloader;
            if (_downloader != null)
            {
                _loaderContext.Downloader = downloader;
                _loaderContext.RemotePath = _downloader.RemotePath;
                _loaderContext.PersistentDataPath = downloader.GetPersistentDataPath();
                FrameworkLog.LogFormat("persistentDataPath {0}", _loaderContext.PersistentDataPath);
                _downloader.AddEventListener(_downloader.BundleDownloadSuccess, OnBundleDownloadSuccess);
            }
            else
            {
                FrameworkLog.LogError("没有找定资源下载器");
            }
            _assetPath = Path.GetDirectoryName(versionFilePath).Replace("\\", "/");
            _loaderContext.CoroutineManager.Start(loadAssetInfo(versionFilePath), "loadConfig");
        }
        private void OnBundleDownloadSuccess(IEventData e)
        {
            var loadFile = _downloader.LoadedFile;
            // Debug.LogError("download " + loadFile.Path);
            var bundleName = GetBundleNameByPath(loadFile.Path, _downloader.CurrentAssetsInfo.AppendHashToAssetBundleName);
            if (_bundleFileInfo.TryGetValue(bundleName, out BundleFileInfo item))
            {
                item.From = FileLoadFrom.PersistentData;
                _loadBundleQueue.Enqueue(item.LoadItem);
            }
            else
            {
                FrameworkLog.LogErrorFormat("不存在bundle文件的信息 {0}", loadFile.Path);
            }
        }
        protected override void loadAsset(AssetLoadData value)
        {
            base.loadAsset(value);
            if (_assetDataMap.TryGetValue(value.Path, out _))
            {
                return;
            }
            var bundlePath = FindBundle(value.Path);
            if (string.IsNullOrEmpty(bundlePath))
            {
                FrameworkLog.LogErrorFormat("not find bundle with assetPath {0}", value.Path);
                value.Finish();
                return;
            }
            var bundle = GetBundleData(bundlePath);
            if (bundle == null)
            {
                FrameworkLog.LogErrorFormat("not find bundleData {0}", bundlePath);
                value.Finish();
                return;
            }
            _workingLoadDataList.Add(value);
            _checkWorkingLoadDataList = true;
            var assetData = _assetDataPool.Get();
            _assetDataMap.Add(value.Path, assetData);
            assetData.Begin(value, bundle);
            var deps = GetDependencies(bundlePath);
            foreach (var item in deps)
            {
                assetData.AddBundleDependencies(item);
            }
            _workingAssetDataList.Add(value.Path);
            _checkWorkingAssetDataList = true;

        }
        protected override void unloadAsset(string path)
        {
            base.unloadAsset(path);
            if (_assetDataMap.TryGetValue(path, out AssetData assetData))
            {
                _assetDataMap.Remove(path);
                _assetDataPool.Release(assetData);
                if (assetData.SceneAsset != null)
                {
                    unloadScene(path);
                }
                assetData.Release();
                _checkUnloadBundles = true;
            }
        }
        private string FindBundle(string assetPath)
        {
            //根据资源名找到bundle名
            //先匹配文件
            //再向上找文件夹
            if (_assetNameToBundleNameMap.TryGetValue(assetPath, out string bundleName))
            {
                return bundleName;
            }
            bundleName = assetPath.ToLower();
            var dotIndex = bundleName.LastIndexOf(".");
            if (dotIndex >= 0)
            {
                bundleName = bundleName.Substring(0, dotIndex);
            }
            int len = 10;
            while (len-- > 0)
            {
                if (_bundleFileInfo.ContainsKey(bundleName))
                {
                    _assetNameToBundleNameMap.Add(assetPath, bundleName);
                    return bundleName;
                }
                var folderIndex = bundleName.LastIndexOf("/");
                if (folderIndex < 0)
                {
                    break;
                }
                bundleName = bundleName.Substring(0, folderIndex);
            }
            return null;

        }
        private string GetBundleNameByPath(string path, bool hasHash)
        {
            var name = Path.GetFileNameWithoutExtension(path);
            if (hasHash)
            {
                var id = name.LastIndexOf("_");
                if (id > 0)
                {
                    name = name.Substring(0, id);
                }
            }
            var dir = Path.GetDirectoryName(path);
            name = Path.Combine(dir, name).Replace("\\", "/");
            return name;
        }

        private IEnumerator loadAssetInfo(string assetsInfoPath)
        {
            yield return null;

            string infoPath;
            UnityWebRequest assetsInfoRequest;
            AssetsInfo persistentDataInfo = null;
            AssetsInfo streamingAssetsInfo = null;

            AppendString(_loaderContext.StreamingAssetsPath, true, true);
            AppendString(assetsInfoPath);
            //从streamingAssetsPath目录加载
            infoPath = GetAppendString();
#if UNITY_WEBGL && !UNITY_EDITOR
                infoPath += "?" + UnityEngine.Random.Range(100000, 9999999) + "_" + (DateTime.Now.Ticks);
#endif
            assetsInfoRequest = UnityWebRequest.Get((new System.Uri(infoPath)).AbsoluteUri);
            yield return assetsInfoRequest.SendWebRequest();
            if (assetsInfoRequest.isDone && assetsInfoRequest.result == UnityWebRequest.Result.Success)
            {
                try
                {
                    AssetsInfo info = AssetsInfo.Decode(assetsInfoRequest.downloadHandler.data);
                    streamingAssetsInfo = info;
                    foreach (var item in info.Bundles)
                    {
                        if (item.Size < 1)
                        {
                            //如果文件大小为0则说明这个文件没有进包内
                            continue;
                        }
                        var binfo = new BundleFileInfo(item, info.AppendHashToAssetBundleName);
                        binfo.From = FileLoadFrom.StreamingAssets;
                        _bundleFileInfo.Add(binfo.BundleName, binfo);
                        //信息里有的条目资源一定也要存在
                    }
                }
                catch (System.Exception e)
                {
                    FrameworkLog.LogError(e);
                }
            }
            assetsInfoRequest.Dispose();

            if (_loaderContext.Downloader.FileSystemEnabled)
            {
                FrameworkLog.Log(_loaderContext.PersistentDataPath);
                //从persistentDataPath目录加载
                AppendString(_loaderContext.PersistentDataPath, true, true);
                AppendString(assetsInfoPath);
                infoPath = GetAppendString(); ;
                if (_loaderContext.Downloader.FileSystem.Exists(infoPath))
                {
                    if (_loaderContext.Downloader.FileSystem.LoadFileEnable())
                    {
                        assetsInfoRequest = UnityWebRequest.Get("file://" + infoPath);
                        yield return assetsInfoRequest.SendWebRequest();
                        if (assetsInfoRequest.isDone && assetsInfoRequest.result == UnityWebRequest.Result.Success)
                        {
                            try
                            {
                                AssetsInfo info = AssetsInfo.Decode(assetsInfoRequest.downloadHandler.data);
                                persistentDataInfo = info;

                            }
                            catch (System.Exception e)
                            {
                                FrameworkLog.LogError(e);
                            }
                        }
                    }
                    else
                    {
                        try
                        {
                            AssetsInfo info = AssetsInfo.Decode(_loaderContext.Downloader.FileSystem.ReadFile(infoPath));
                            persistentDataInfo = info;

                        }
                        catch (System.Exception e)
                        {
                            FrameworkLog.LogError(e);
                        }
                    }

                    if (persistentDataInfo != null)
                    {
                        foreach (var item in persistentDataInfo.Bundles)
                        {
                            AppendString(_loaderContext.PersistentDataPath, true, true);
                            AppendString(_assetPath, true);
                            AppendString(item.Path);
                            var bundlePath = GetAppendString();
                            bool fileExist = _loaderContext.Downloader.FileSystem.Exists(bundlePath);
                            var bfinfo = new BundleFileInfo(item, persistentDataInfo.AppendHashToAssetBundleName);
                            if (_bundleFileInfo.TryGetValue(bfinfo.BundleName, out BundleFileInfo binfo))
                            {
                                if (binfo.Info.Hash0 != item.Hash0 && binfo.Info.Hash1 != item.Hash1)
                                {
                                    // 这个资源有更新 
                                    _bundleFileInfo[bfinfo.BundleName] = bfinfo;
                                    binfo.From = fileExist ? FileLoadFrom.PersistentData : FileLoadFrom.Download;
                                }
                            }
                            else
                            {
                                // 内置包里不存在这个资源
                                _bundleFileInfo.Add(bfinfo.BundleName, bfinfo);
                                bfinfo.From = fileExist ? FileLoadFrom.PersistentData : FileLoadFrom.Download;
                            }
                        }
                    }

                    assetsInfoRequest.Dispose();
                }
                string manifestFile = string.Empty;
                if (persistentDataInfo != null)
                {
                    _assetsInfo = persistentDataInfo;
                }
                else if (streamingAssetsInfo != null)
                {
                    _assetsInfo = streamingAssetsInfo;
                }
                else
                {
                    _assetsInfo = null;
                    FrameworkLog.LogError("如果资源没有放到内置包,那就要把资源文件下载到用户目录");
                }
            }
            else
            {
                _assetsInfo = _downloader.RemoteAssetsInfo;
                foreach (var item in _assetsInfo.Bundles)
                {
                    var binfo = new BundleFileInfo(item, _assetsInfo.AppendHashToAssetBundleName);
                    if (_bundleFileInfo.TryGetValue(binfo.BundleName, out BundleFileInfo einfo))
                    {
                        binfo = einfo;
                    }
                    else
                    {
                        _bundleFileInfo.Add(binfo.BundleName, binfo);
                    }
                    binfo.From = FileLoadFrom.Remote;

                }
            }

            if (_assetsInfo != null)
            {
                this.Enabled = true;
                _bundleDataPool = new CustomPool<BundleData>(() => { return new BundleData(); }, _assetsInfo.Bundles.Length);
                _assetDataPool = new CustomPool<AssetData>(() => { return new AssetData(_assetsInfo.AssetCount); }, _assetsInfo.AssetCount / 2);
                var list = new List<BundleFileInfo>();
                foreach (var item in _assetsInfo.Bundles)
                {
                    var bundleName = GetBundleNameByPath(item.Path, _assetsInfo.AppendHashToAssetBundleName);
                    if (_bundleFileInfo.TryGetValue(bundleName, out var binfo))
                    {
                        list.Add(binfo);
                    }
                }
                _bundleFileInfo.Clear();
                foreach (var item in list)
                {
                    _bundleFileInfo.Add(item.BundleName, item);
                    if (item.Info.Encrypt > 0)
                    {
                        if (item.Info.Size > _loaderContext.MaxSizeOfEncryptFile)
                        {
                            _loaderContext.MaxSizeOfEncryptFile = item.Info.Size;
                        }
                    }
                }
                if (_assetProcessor != null)
                {
                    _assetProcessor.InitAssetsInfo(_assetsInfo.Clone());
                }
            }
        }
        private BundleData GetBundleData(string path)
        {
            if (_bundleDataMap.TryGetValue(path, out BundleData data))
            {
                return data;
            }
            if (_bundleFileInfo.TryGetValue(path, out BundleFileInfo fileInfo))
            {
                data = _bundleDataPool.Get();
                data.Begin(path);
                _bundleDataMap.Add(path, data);
                var loaddata = _loadBundleItemPool.Get();
                loaddata.Begin(data, fileInfo);
                fileInfo.LoadItem = loaddata;
                _loadBundleQueue.Enqueue(loaddata);
                return data;
            }
            else
            {
                FrameworkLog.LogErrorFormat("没有找到{0} 的文件信息", path);
            }
            return null;
        }


        private List<BundleData> GetDependencies(string bundle)
        {
            _tempDependenciesMap.Clear();
            _tempDependenciesList.Clear();
            var bundleData = GetBundleData(bundle);
            _tempDependenciesList.Add(bundleData);
            _tempDependenciesMap.Add(bundle, bundleData);
            GetDepends(bundle);
            return _tempDependenciesList;
        }
        private void GetDepends(string bundle)
        {
            if (!_dependenciesMap.TryGetValue(bundle, out string[] list))
            {
                _driectDependencies.Clear();
                if (_bundleFileInfo.TryGetValue(bundle, out var binfo))
                {
                    _assetsInfo.GetDirectDependencies(binfo.Info, _driectDependencies);
                    var len = _driectDependencies.Count;
                    list = new string[_driectDependencies.Count];
                    for (var i = 0; i < len; i++)
                    {
                        list[i] = _driectDependencies[i];
                    }
                    _dependenciesMap.Add(bundle, list);
                }
                else
                {
                    Debug.LogError("not find bundle info " + bundle);
                }

            }
            foreach (var item in list)
            {
                if (_tempDependenciesMap.ContainsKey(item)) continue;
                var bundleName = GetBundleNameByPath(item, _assetsInfo.AppendHashToAssetBundleName);
                var bundleData = GetBundleData(bundleName);
                if (bundleData == null)
                {
                    FrameworkLog.LogError("not find file {0} " + item);
                    continue;
                }
                _tempDependenciesMap.Add(item, bundleData);
                _tempDependenciesList.Add(bundleData);
                GetDepends(bundleName);
            }
        }
        private void loadBundleFinish(LoadBundleItem value)
        {
            if (!value.Success)
            {
                if (value.ReytryCount > 0)
                {
                    _loadBundleQueue.Enqueue(value);
                }
                else
                {
                    FrameworkLog.LogError("bundle 加载失败 {0} " + value.BundleData.Path);
                }
                return;
            }
            if (_assetProcessor != null)
            {
                if (value.BundleData.AssetBundle != null)
                {
                    _assetProcessor.OnLoadBundle(value.BundleData.AssetBundle, value.BundleData.Path);
                }
            }
            _checkWorkingAssetDataList = true;
            _loadBundleItemPool.Release(value);

        }
        private void loadAssetFinish(AssetData value)
        {
            _checkWorkingLoadDataList = true;
        }

        internal class AssetData
        {
            public bool Finished { get; private set; }
            public string Path { get; private set; }
            public BundleData Bundle { get; private set; }
            public object Asset { get; private set; }
            public AsyncOperation SceneAsset { get; private set; }
            public AssetLoadData LoadData { get; private set; }
            public List<BundleData> Bundles { get; private set; }
            private List<BundleData> _bundles;
            public AssetData(int bundleCount)
            {
                _bundles = new List<BundleData>(bundleCount >> 1);
                Bundles = new List<BundleData>(bundleCount >> 1);
            }
            public void Release()
            {
                if (SceneAsset != null && LoadData.IsScene)
                {
                    SceneManager.UnloadSceneAsync(this.LoadData.Path, UnloadSceneOptions.UnloadAllEmbeddedSceneObjects);
                }
                foreach (var item in _bundles)
                {
                    item.RemoveRef();
                }
                _bundles.Clear();
                Bundle = null;
                this.Finished = false;
                this.Bundles.Clear();
                this.LoadData = null;
                this.SceneAsset = null;
                this.Asset = null;
            }
            public void Begin(AssetLoadData loadData, BundleData bundle)
            {
                this.Finished = false;
                this.LoadData = loadData;
                this.Path = loadData.Path;
                this.Bundle = bundle;
                _bundles.Clear();
                Bundles.Clear();
                this.Asset = null;
                this.SceneAsset = null;
            }
            public void AddBundleDependencies(BundleData value)
            {
                _bundles.Add(value);
                Bundles.Add(value);
                value.AddRef();
            }
            public void Execute()
            {
                var len = Bundles.Count;
                while (len-- > 0)
                {
                    var bundle = Bundles[len];
                    if (bundle.Finished)
                    {
                        Bundles.RemoveAt(len);
                    }
                }
            }
            public IEnumerator Load(Action<AssetData> finishCallback)
            {
                if (LoadData.RefCount > 0)
                {
                    if (LoadData.IsScene)
                    {
                        AsyncOperation asyncOperation = SceneManager.LoadSceneAsync(this.LoadData.Path, LoadSceneMode.Additive);
                        if (asyncOperation != null)
                        {
                            asyncOperation.allowSceneActivation = false;
                        }
                        this.Asset = this.SceneAsset = asyncOperation;
                        this.Finished = true;
                    }
                    else
                    {
                        AssetBundleRequest bundleRequest = this.Bundle.AssetBundle.LoadAssetAsync(this.LoadData.Path);
                        yield return bundleRequest;
                        this.Asset = bundleRequest.asset;
                        this.Finished = true;
                    }
                }
                else
                {
                    this.Asset = null;
                    this.SceneAsset = null;
                    this.Finished = true;
                }

                finishCallback.Invoke(this);
            }
        }
        internal class BundleFileInfo
        {
            public string BundleName { get; private set; }
            public BundleInfo Info;
            public FileLoadFrom From;
            public LoadBundleItem LoadItem;
            public BundleFileInfo(BundleInfo value, bool AppendHashToAssetBundleName)
            {
                this.Info = value;
                BundleName = GetBundleNameByPath(value.Path, AppendHashToAssetBundleName);
            }
            private string GetBundleNameByPath(string path, bool hasHash)
            {
                var name = Path.GetFileNameWithoutExtension(path);
                if (hasHash)
                {
                    var id = name.LastIndexOf("_");
                    if (id > 0)
                    {
                        name = name.Substring(0, id);
                    }
                }
                var dir = Path.GetDirectoryName(path);
                name = Path.Combine(dir, name).Replace("\\", "/");
                return name;
            }
        }
        internal enum FileLoadFrom
        {
            //内置包
            StreamingAssets,
            //用户数据
            PersistentData,
            //远程
            Remote,
            // 现在缓存
            Download,
        }
        internal class BundleData
        {
            public AssetBundle AssetBundle { get; private set; }
            public bool Finished { get; private set; }
            public string Path { get; private set; }
            public int RefCount { get; private set; }
            public void AddRef()
            {
                RefCount++;
            }
            public void RemoveRef()
            {
                RefCount--;
            }
            public void Begin(string path)
            {
                this.Finished = false;
                this.Path = path;
                RefCount = 0;
                AssetBundle = null;
            }
            public void Finish(AssetBundle value)
            {
                this.AssetBundle = value;
                this.Finished = true;
            }
            public void Release()
            {
                if (AssetBundle == null)
                {
                    return;
                }
                // FrameworkLog.LogFormat("bundle unload {0} ", Path);
                this.AssetBundle.Unload(true);
                this.AssetBundle = null;
            }
        }
        internal class LoadBundleItem
        {
            //加密文件最大的大小
            private static byte[] _encryptBuffer;
            private static byte[] _readBuffer;
            public int ReytryCount { get; private set; }
            public bool Success { get; private set; }
            public BundleData BundleData { get; private set; }
            public BundleFileInfo Info { get; private set; }
            public void Begin(BundleData value, BundleFileInfo info)
            {
                this.BundleData = value;
                Info = info;
                Success = false;
                ReytryCount = 3;
            }
            public IEnumerator Load(LoaderContext context, string path, Action<LoadBundleItem> successCallback)
            {
                ReytryCount--;
                Success = false;
                string loadPath = string.Empty;
                if (Info.From == FileLoadFrom.Remote)
                {
                    AssetLoader.AppendString(context.RemotePath, true, true);
                    AssetLoader.AppendString(path, true);
                    AssetLoader.AppendString(Info.Info.Path);
                    loadPath = AssetLoader.GetAppendString();
                }
                else
                {
                    if (context.Downloader.FileSystemEnabled)
                    {
                        AssetLoader.AppendString(context.PersistentDataPath, true, true);
                        AssetLoader.AppendString(path, true);
                        AssetLoader.AppendString(Info.Info.Path);
                        loadPath = AssetLoader.GetAppendString();
                        if (!context.Downloader.FileSystem.Exists(loadPath))
                        {
                            loadPath = string.Empty;
                        }
                    }
                }
                if (string.IsNullOrEmpty(loadPath))
                {
                    AssetLoader.AppendString(context.StreamingAssetsPath, true, true);
                    AssetLoader.AppendString(path, true);
                    AssetLoader.AppendString(Info.Info.Path);
                    loadPath = AssetLoader.GetAppendString();
#if UNITY_WEBGL && !UNITY_EDITOR
                    loadPath += "?" + Info.Info.Hash0 + "_" + Info.Info.Hash1;
#endif
                }
                if (context.BundleProcessor != null)
                {
                    loadPath = context.BundleProcessor.GetBundleAssetPath(loadPath);
                }
                var uri = new System.Uri(loadPath);
                FrameworkLog.LogFormat("load bundle file {0}", uri.AbsoluteUri);
                UnityWebRequest webRequest;
                if (Info.Info.Encrypt > 0)
                {
                    FrameworkLog.LogError("需要解密资源 " + Info.Info.Path);
                    if (context.AssetProcessor != null)
                    {
                        if (_encryptBuffer == null)
                        {
                            var buffsize = context.MaxSizeOfEncryptFile;
                            if (buffsize < 1)
                            {
                                buffsize = 1024 * 1024 * 10;
                            }
                            _encryptBuffer = new byte[buffsize];
                            _readBuffer = new byte[1024 * 100];
                            // Debug.LogError("创建解密buffer");
                        }
                        if (Info.From == FileLoadFrom.PersistentData)
                        {
                            var stream = context.AssetProcessor.GetFile(uri.AbsoluteUri);
                            if (stream == null)
                            {
                                webRequest = UnityWebRequest.Get(uri.AbsoluteUri);
                                var downloadHandler = new DownloadFileBufferHandler(_readBuffer);
                                downloadHandler.SetBuffer(_encryptBuffer);
                                webRequest.downloadHandler = downloadHandler;
                                webRequest.disposeUploadHandlerOnDispose = true;
                                yield return webRequest.SendWebRequest();
                                if (!Utils.Unity.IsUnityWebRequestError(webRequest))
                                {
                                    stream = context.AssetProcessor.ProcessFile(uri.AbsoluteUri, _encryptBuffer, downloadHandler.Length, 0);
                                }
                                else
                                {
                                    FrameworkLog.LogErrorFormat("UnityWebRequest load file error {0}", loadPath);
                                }
                                webRequest.Dispose();
                            }
                            if (stream != null)
                            {
                                AssetBundleCreateRequest assetBundleCreateRequest = AssetBundle.LoadFromStreamAsync(stream);
                                yield return assetBundleCreateRequest;
                                this.BundleData.Finish(assetBundleCreateRequest.assetBundle);
                                Success = assetBundleCreateRequest.assetBundle != null;
                                successCallback.Invoke(this);
                            }
                        }
                        else
                        {
                            webRequest = UnityWebRequest.Get(uri.AbsoluteUri);
                            webRequest.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();
                            yield return webRequest.SendWebRequest();
                            if (!Utils.Unity.IsUnityWebRequestError(webRequest))
                            {
                                var buffer = webRequest.downloadHandler.data;
                                context.AssetProcessor.ProcessFile(buffer);
                                AssetBundleCreateRequest assetBundleCreateRequest = AssetBundle.LoadFromMemoryAsync(buffer);
                                yield return assetBundleCreateRequest;
                                this.BundleData.Finish(assetBundleCreateRequest.assetBundle);
                                Success = assetBundleCreateRequest.assetBundle != null;
                                successCallback.Invoke(this);
                                webRequest.Dispose();
                            }
                        }
                        yield break;
                    }
                }
                webRequest = UnityWebRequestAssetBundle.GetAssetBundle(uri.AbsoluteUri);
                yield return webRequest.SendWebRequest();
                if (webRequest.isDone && webRequest.result == UnityWebRequest.Result.Success)
                {
                    if (webRequest.downloadHandler is DownloadHandlerAssetBundle downloadBundle)
                    {
                        if (downloadBundle.assetBundle != null)
                        {
                            this.BundleData.Finish(downloadBundle.assetBundle);
                            Success = downloadBundle.assetBundle != null;
                        }
                        else
                        {
                            int size = Framework.Utils.Unity.GetDownloadHandlerSize(webRequest.downloadHandler);
                            if (size != Info.Info.Size)
                            {
                                FrameworkLog.LogErrorFormat("UnityWebRequestAssetBundle siz error {0} need {1} but {2}", loadPath, Info.Info.Size, size);
                            }
                        }
                    }

                }
                else
                {
                    FrameworkLog.LogErrorFormat("UnityWebRequestAssetBundle load error {0}", loadPath);
                }
                successCallback.Invoke(this);
                webRequest.Dispose();
            }
        }
    }
}